package org.rsbot.script.internal;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.rsbot.bot.Bot;
import org.rsbot.script.Random;
import org.rsbot.script.Script;
import org.rsbot.script.ScriptManifest;
import org.rsbot.script.internal.event.ScriptListener;
import org.rsbot.script.randoms.BankPins;
import org.rsbot.script.randoms.BeehiveSolver;
import org.rsbot.script.randoms.CapnArnav;
import org.rsbot.script.randoms.Certer;
import org.rsbot.script.randoms.CloseAllInterface;
import org.rsbot.script.randoms.DrillDemon;
import org.rsbot.script.randoms.Exam;
import org.rsbot.script.randoms.FirstTimeDeath;
import org.rsbot.script.randoms.FreakyForester;
import org.rsbot.script.randoms.FrogCave;
import org.rsbot.script.randoms.GraveDigger;
import org.rsbot.script.randoms.ImprovedRewardsBox;
import org.rsbot.script.randoms.LeaveSafeArea;
import org.rsbot.script.randoms.LoginBot;
import org.rsbot.script.randoms.LostAndFound;
import org.rsbot.script.randoms.Maze;
import org.rsbot.script.randoms.Mime;
import org.rsbot.script.randoms.Molly;
import org.rsbot.script.randoms.Pillory;
import org.rsbot.script.randoms.Pinball;
import org.rsbot.script.randoms.Prison;
import org.rsbot.script.randoms.QuizSolver;
import org.rsbot.script.randoms.SandwhichLady;
import org.rsbot.script.randoms.ScapeRuneIsland;
import org.rsbot.script.randoms.SystemUpdate;
import org.rsbot.script.randoms.TeleotherCloser;

public class ScriptHandler
{
  private ArrayList<Random> randoms = new ArrayList();
  private HashMap<Integer, Script> scripts = new HashMap();
  private HashMap<Integer, Thread> scriptThreads = new HashMap();

  private Set<ScriptListener> listeners = Collections.synchronizedSet(new HashSet());
  private Bot bot;

  public ScriptHandler(Bot paramBot)
  {
    this.bot = paramBot;
  }

  public void init() {
    try {
      this.randoms.add(new LoginBot());
      this.randoms.add(new BankPins());
      this.randoms.add(new BeehiveSolver());
      this.randoms.add(new CapnArnav());
      this.randoms.add(new Certer());
      this.randoms.add(new CloseAllInterface());
      this.randoms.add(new DrillDemon());
      this.randoms.add(new FreakyForester());
      this.randoms.add(new FrogCave());
      this.randoms.add(new GraveDigger());
      this.randoms.add(new ImprovedRewardsBox());
      this.randoms.add(new LostAndFound());
      this.randoms.add(new Maze());
      this.randoms.add(new Mime());
      this.randoms.add(new Molly());
      this.randoms.add(new Exam());
      this.randoms.add(new Pillory());
      this.randoms.add(new Pinball());
      this.randoms.add(new Prison());
      this.randoms.add(new QuizSolver());
      this.randoms.add(new SandwhichLady());
      this.randoms.add(new ScapeRuneIsland());
      this.randoms.add(new TeleotherCloser());
      this.randoms.add(new FirstTimeDeath());
      this.randoms.add(new LeaveSafeArea());
      this.randoms.add(new SystemUpdate());
    } catch (Exception localException) {
      localException.printStackTrace();
    }
    for (Random localRandom : this.randoms)
      localRandom.init(this.bot.getMethodContext());
  }

  public void addScriptListener(ScriptListener paramScriptListener)
  {
    this.listeners.add(paramScriptListener);
  }

  public void removeScriptListener(ScriptListener paramScriptListener) {
    this.listeners.remove(paramScriptListener);
  }

  private void addScriptToPool(Script paramScript, Thread paramThread) {
    for (int i = 0; i < this.scripts.size(); i++) {
      if (!this.scripts.containsKey(Integer.valueOf(i))) {
        this.scripts.put(Integer.valueOf(i), paramScript);
        paramScript.setID(i);
        this.scriptThreads.put(Integer.valueOf(i), paramThread);
        return;
      }
    }
    paramScript.setID(this.scripts.size());
    this.scripts.put(Integer.valueOf(this.scripts.size()), paramScript);
    this.scriptThreads.put(Integer.valueOf(this.scriptThreads.size()), paramThread);
  }

  public Bot getBot() {
    return this.bot;
  }

  public Collection<Random> getRandoms() {
    return this.randoms;
  }

  public Map<Integer, Script> getRunningScripts() {
    return Collections.unmodifiableMap(this.scripts);
  }

  public void pauseScript(int paramInt) {
    Script localScript = (Script)this.scripts.get(Integer.valueOf(paramInt));
    localScript.setPaused(!localScript.isPaused());
    Iterator localIterator;
    ScriptListener localScriptListener;
    if (localScript.isPaused())
      for (localIterator = this.listeners.iterator(); localIterator.hasNext(); ) { localScriptListener = (ScriptListener)localIterator.next();
        localScriptListener.scriptPaused(this, localScript);
      }
    else
      for (localIterator = this.listeners.iterator(); localIterator.hasNext(); ) { localScriptListener = (ScriptListener)localIterator.next();
        localScriptListener.scriptResumed(this, localScript);
      }
  }

  public void stopScript(int paramInt)
  {
    Script localScript = (Script)this.scripts.get(Integer.valueOf(paramInt));
    if (localScript != null) {
      localScript.deactivate(paramInt);
      this.scripts.remove(Integer.valueOf(paramInt));
      this.scriptThreads.remove(Integer.valueOf(paramInt));
      for (ScriptListener localScriptListener : this.listeners)
        localScriptListener.scriptStopped(this, localScript);
    }
  }

  public void runScript(Script paramScript)
  {
    paramScript.init(this.bot.getMethodContext());
    for (Object localObject1 = this.listeners.iterator(); ((Iterator)localObject1).hasNext(); ) { localObject2 = (ScriptListener)((Iterator)localObject1).next();
      ((ScriptListener)localObject2).scriptStarted(this, paramScript);
    }
    localObject1 = (ScriptManifest)paramScript.getClass().getAnnotation(ScriptManifest.class);
    Object localObject2 = new Thread(paramScript, "Script-" + ((ScriptManifest)localObject1).name());
    addScriptToPool(paramScript, (Thread)localObject2);
    ((Thread)localObject2).start();
  }

  public void stopAllScripts() {
    for (Iterator localIterator = this.scripts.keySet().iterator(); localIterator.hasNext(); ) { int i = ((Integer)localIterator.next()).intValue();
      stopScript(i); }
  }

  public void stopScript()
  {
    Thread localThread = Thread.currentThread();
    for (int i = 0; i < this.scripts.size(); i++) {
      Script localScript = (Script)this.scripts.get(Integer.valueOf(i));
      if ((localScript == null) || (!localScript.isRunning()) || 
        (this.scriptThreads.get(Integer.valueOf(i)) != localThread)) continue;
      stopScript(i);
    }

    if (localThread == null)
      throw new ThreadDeath();
  }

  public void updateInput(Bot paramBot, int paramInt)
  {
    for (ScriptListener localScriptListener : this.listeners)
      localScriptListener.inputChanged(paramBot, paramInt);
  }
}